package org.as3search.config {
	/*
	 * as3search - http://code.google.com/p/as3search
	 * Copyright (c) 2009-2010 by respective authors. All rights reserved.
	 *
	 * This library is free software; you can redistribute it and/or modify it under the
	 * terms of the GNU Lesser General Public License as published by the Free Software
	 * Foundation; either version 2.1 of the License, or (at your option) any later
	 * version.
	 *
	 * This library is distributed in the hope that it will be useful, but WITHOUT ANY
	 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
	 * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
	 *
	 * You should have received a copy of the GNU Lesser General Public License along
	 * with this library; if not, write to the Free Software Foundation, Inc.,
	 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
	 */	
	
	import org.flexunit.Assert;
	
	import mx.collections.ArrayList;
	import mx.collections.IList;
	
	import org.as3search.criteria.impl.CriteriaImpl;
	import org.as3search.properties.DefaultPropertyResolver;
	import org.as3search.properties.PropertyResolver;
	import org.as3search.providers.ArraySearchProvider;
	import org.as3search.providers.FlexListSearchProvider;
	import org.as3search.providers.ObjectSearchProvider;
	import org.as3search.providers.SearchProviderMapping;
	import org.as3search.providers.impl.SearchProviderMappingImpl;
	
	/**
	 * 
	 */
	public class AbstractSearchConfigurationTestCase {
		
		private var classToTestRef:org.as3search.config.AbstractSearchConfiguration;
		
		public function AbstractSearchConfigurationTestCase() {
			
		}
		
		[Before]
		public function setup():void {
			classToTestRef = new AbstractSearchConfiguration();
		}
		
		[Test]
		public function testCreateCriteria():void {
			classToTestRef.addSearchProvider(Array, ArraySearchProvider);
			
			var criteria:CriteriaImpl = CriteriaImpl(classToTestRef.createCriteria([{id:0}]));
			Assert.assertNotNull("createCriteria() should never return null",
				criteria);
			Assert.assertNotNull("criteria.provider should not be null",
				criteria.provider);
			Assert.assertTrue("criteria.provider should be ArraySearchProvider",
				criteria.provider is ArraySearchProvider);
			Assert.assertEquals("criteria.configuration should equal our configuration",
				classToTestRef, criteria.configuration);
		}
		
		[Test]
		public function testPropertyResolver():void {
			Assert.assertNotNull("'propertyResolver' should not be null",
				classToTestRef.propertyResolver);
			var propResolver:PropertyResolver = new DefaultPropertyResolver();
			classToTestRef.propertyResolver = propResolver;
			Assert.assertEquals("failed to set 'propertyResolver'",
				propResolver, classToTestRef.propertyResolver);
		}
		
		[Test]
		public function testAddSearchProvider():void {
			classToTestRef.addSearchProvider(IList, FlexListSearchProvider);
			var found:Boolean = false;
			for each (var providerMapping:SearchProviderMapping in classToTestRef.providers) {
				if (providerMapping.targetType == IList && providerMapping.providerType == FlexListSearchProvider) {
					found = true;
					break;
				}
			}
			Assert.assertTrue("did not add the search provider to the provider list",
				found);
		}
		
		[Test]
		public function testFailoverProvider():void {
			var fp:SearchProviderMapping = new SearchProviderMappingImpl(Object, ObjectSearchProvider);
			classToTestRef.failoverProvider = fp;
			Assert.assertEquals("failed to set the 'failoverProvider'",
				classToTestRef.failoverProvider, fp);
		}
		
		[Test]
		public function testGetSearchProvider():void {
//			test first in all providers
			classToTestRef.addSearchProvider(Array, ArraySearchProvider);
			Assert.assertTrue("failed to return the best appropriate provider",
				classToTestRef.getSearchProvider([]) is ArraySearchProvider);
//			then test for the default
			classToTestRef.failoverProvider = new SearchProviderMappingImpl(Object, ObjectSearchProvider);
			Assert.assertTrue("failed to return the default provider",
				classToTestRef.getSearchProvider({a:"b"}) is ObjectSearchProvider);
		}
		
		[Test]
		public function testProviders():void {
//			test if it sets ok
			var mapping:SearchProviderMapping = new SearchProviderMappingImpl(Array, ArraySearchProvider);
			Assert.assertNotNull("failed to maintain 'providers' not null",
				classToTestRef.providers);
			classToTestRef.providers = null;
			Assert.assertNotNull("failed to set 'providers' as empty array when assigned to null",
				classToTestRef.providers);
			classToTestRef.providers = [mapping];
			Assert.assertEquals("failed to set 'providers'",
				classToTestRef.providers.indexOf(mapping), 0);
//			try and break it
			try {
				classToTestRef.providers = [1,"abc"];
				Assert.fail("did not throw error when a foreign object is in 'providers'");
			} catch (e:ArgumentError) {
//				pass
			}
		}
		
		[Test]
		public function testRemoveSearchProvider():void {
			classToTestRef.failoverProvider = new SearchProviderMappingImpl(Object, ObjectSearchProvider);
			classToTestRef.addSearchProvider(IList, FlexListSearchProvider);
			Assert.assertTrue("failed to add the provider in the first place",
				classToTestRef.getSearchProvider(new ArrayList()) is FlexListSearchProvider);
			classToTestRef.removeSearchProvider(IList);
			Assert.assertTrue("failed to remove the provider",
				classToTestRef.getSearchProvider(new ArrayList()) is ObjectSearchProvider);
		}
	}
}